#include "cnfield.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <memory.h>

using namespace std;
using namespace opsrc::stdf; 

template <typename T, int L>   
CnField<T,L>::CnField() {
	blen = L;
}

template <typename T, int L>
CnField<T,L>::CnField(char* buf, endian e):blen(L), en(e) {
	this->data = decode(buf);	
}

template <typename T, int L>   
CnField<T,L>::~CnField() {
}

template <typename T, int L>
T CnField<T,L>::getData() const {
  return data;	
}

template <typename T, int L>
T CnField<T,L>::decode(char* buf) {
	
	// Determine if L=-1, the length is derived by reading the first byte of the 
	// pass-in buf character. If not, just read buf where the length is determined by 
	// L, the length of byte to read from buf.
	if (L<=0) {
		// first byte is the length
		int len = *buf;
		if (len > 0 ) {
			char item[len+1];  // add one for char array termination
    		::memcpy(item, /* offset by 1 byte */ buf+1, len);
    		item[len] = '\0';  // assign last index as non-terminal
    	
    		// save the len value
    		blen = len;  // include the first byte which is the bytecount value
    		T so(item);
    		return so;
		}
		else {
			blen = 0;
			T so(" ");
			return so;	
		}
	} 
	else {
		blen = L;
		char item[blen+1];  // add one for char array termination
    	::memcpy(item, /* offset by 1 byte */ buf, blen);
    	item[blen] = '\0';  // assign last index as non-terminal
   		T so(item);
   		return so;
	}

}

template <typename T, int L>
int CnField<T,L>::getByteCount() const {
   return blen;	 
}


template <typename T, int L>
int CnField<T,L>::getTotalByteCount() const {
   if ( L < 1 )
      return blen + 1 ; // account for the first byte, which holds the byte count
   else
      return blen;   
	
}


// **************************************************
// Specialization for CharArray class
// **************************************************
template <int L>
CnField<CharArray,L>::CnField() {
}

template <int L>
CnField<CharArray,L>::CnField(char *buf, endian e):en(e) {
	decode(buf);
}

template <int L>
CnField<CharArray,L>::~CnField() {
}

template <int L>
CharArray CnField<CharArray,L>::decode(char* buf) {
	// If little endian, swap byte order
	// where least significant byte is at lower address 
	// For big endian, the most significant byte is at the lower address
	
	if (L<1) {
	   	// read first byte for length, no need to swamp as its only 1 byte	
	   	len = *buf;
		
		if (len>0) {
		  CharArray ca(buf+1, len);
		  data = ca;
		}
	} 
	else {
		
		if (L > 0) {
		   len = L;	
		   CharArray ca(buf, len);
		   data = ca;
		}
		else {
			len = 0;
		}

	}

	return data;
}

template <int L>
int CnField<CharArray,L>::getByteCount() const {
    return len;	
}

template <int L>
CharArray CnField<CharArray,L>::getData() const {
  return data;	
}

template <int L>
int CnField<CharArray,L>::getTotalByteCount() const {
	// account for the first byte, which holds the byte count
   return ( L < 1 )? len+1 : len;

}

